package cn.daniellee.plugin.ce.storage;

import cn.daniellee.plugin.ce.CraftEconomy;
import cn.daniellee.plugin.ce.model.PlayerData;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class MysqlStorage extends Storage {

	private Connection connection;

	private String tablePrefix;

	@Override
	public boolean initialize() {
		// 初始化Mysql驱动
		try {
			Class.forName("com.mysql.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			CraftEconomy.getInstance().getLogger().info(" ");
			CraftEconomy.getInstance().getLogger().info("[CraftEconomy]An error occurred while getting the Mysql database driver.".replace("&", "§"));
			CraftEconomy.getInstance().getLogger().info(" ");
			return false;
		}
		// 初始化连接
		String url = "jdbc:mysql://" + CraftEconomy.getInstance().getConfig().getString("storage.mysql.host", "localhost") + ":" + CraftEconomy.getInstance().getConfig().getInt("storage.mysql.port", 3306) + "/" + CraftEconomy.getInstance().getConfig().getString("storage.mysql.database", "minecraft") + "?" + CraftEconomy.getInstance().getConfig().getString("storage.mysql.parameter", "characterEncoding=utf-8&useSSL=false&autoReconnect=true");
		try {
			connection = DriverManager.getConnection(url, CraftEconomy.getInstance().getConfig().getString("storage.mysql.username", "username"), CraftEconomy.getInstance().getConfig().getString("storage.mysql.password", "password"));
		} catch (SQLException e) {
			e.printStackTrace();
			CraftEconomy.getInstance().getLogger().info(" ");
			CraftEconomy.getInstance().getLogger().info("[CraftEconomy]Mysql connection information is incorrect.".replace("&", "§"));
			CraftEconomy.getInstance().getLogger().info(" ");
			return false;
		}
		// 初始化数据表
		tablePrefix = CraftEconomy.getInstance().getConfig().getString("storage.mysql.table_perfix", "ce_");
		String sql = "CREATE TABLE IF NOT EXISTS `" + tablePrefix + "player` (" +
				"`uuid` varchar(48)," +
				"`name` varchar(48)," +
				"`balance` double(20,2) NOT NULL DEFAULT '0.00'" +
				") ENGINE=InnoDB DEFAULT CHARSET=utf8;";
		PreparedStatement statement = null;
		try {
			statement = connection.prepareStatement(sql);
			statement.execute();
		} catch (SQLException e) {
			e.printStackTrace();
			CraftEconomy.getInstance().getLogger().info(" ");
			CraftEconomy.getInstance().getLogger().info("[CraftEconomy]An error occurred while initializing the Mysql data table.".replace("&", "§"));
			CraftEconomy.getInstance().getLogger().info(" ");
			return false;
		} finally {
			if (statement != null) {
				try {
					statement.close();
				} catch (SQLException ignored) { }
			}
		}
		List<PlayerData> allPlayerData = getAllPlayerData();
		allPlayerData.forEach(item -> allPlayerDataCache.put(CraftEconomy.getInstance().isOnlineMode() ? item.getUuid() : item.getName(), item));
		return true;
	}

	@Override
	public PlayerData refreshPlayerData(String targetPlayer) {
		PreparedStatement statement = null;
		try {
			String sql = "select * from " + tablePrefix + "player where " + (CraftEconomy.getInstance().isOnlineMode() ? "uuid" : "name") +  " = ?";
			statement = connection.prepareStatement(sql);
			statement.setString(1, targetPlayer);
			ResultSet resultSet = statement.executeQuery();
			if (resultSet.next()) {
				PlayerData playerData = new PlayerData();
				playerData.setUuid(resultSet.getString("uuid"));
				playerData.setName(resultSet.getString("name"));
				playerData.setBalance(resultSet.getDouble("balance"));
				allPlayerDataCache.put(targetPlayer, playerData);
				return playerData;
			} else {
				insertPlayerData(targetPlayer, CraftEconomy.getInstance().getConfig().getDouble("setting.initial-balance", 500.00D));
				return refreshPlayerData(targetPlayer);
			}
		} catch (SQLException e) {
			e.printStackTrace();
			CraftEconomy.getInstance().getLogger().info(" ");
			CraftEconomy.getInstance().getLogger().info("[CraftEconomy]An error occurred while reading player data from Mysql.".replace("&", "§"));
			CraftEconomy.getInstance().getLogger().info(" ");
		} finally {
			if (statement != null) {
				try {
					statement.close();
				} catch (SQLException ignored) { }
			}
		}
		return null;
	}

	@Override
	public void updatePlayerData(String targetPlayer, String column, Object value) {
		PreparedStatement statement = null;
		try {
			String sql = "update " + tablePrefix + "player set " + column + " = ? where " + (CraftEconomy.getInstance().isOnlineMode() ? "uuid" : "name") + " = ?";
			statement = connection.prepareStatement(sql);
			statement.setObject(1, value);
			statement.setString(2, targetPlayer);
			statement.executeUpdate();
			PlayerData playerData = getPlayerData(targetPlayer);
			switch (column) {
				case "uuid":
					playerData.setUuid((String) value);
					break;
				case "name":
					playerData.setName((String) value);
					break;
				case "balance":
					playerData.setBalance((Double) value);
					break;
			}
		} catch (SQLException e) {
			e.printStackTrace();
			CraftEconomy.getInstance().getLogger().info(" ");
			CraftEconomy.getInstance().getLogger().info("[CraftEconomy]An error occurred while updating player data from Mysql.".replace("&", "§"));
			CraftEconomy.getInstance().getLogger().info(" ");
		} finally {
			if (statement != null) {
				try {
					statement.close();
				} catch (SQLException ignored) { }
			}
		}
	}

	@Override
	public List<PlayerData> getAllPlayerData() {
		List<PlayerData> allPlayerData = new ArrayList<>();
		PreparedStatement statement = null;
		try {
			String sql = "select * from " + tablePrefix + "player";
			statement = connection.prepareStatement(sql);
			ResultSet resultSet = statement.executeQuery();
			while (resultSet.next()) {
				PlayerData playerData = new PlayerData();
				playerData.setUuid(resultSet.getString("uuid"));
				playerData.setName(resultSet.getString("name"));
				playerData.setBalance(resultSet.getDouble("balance"));
				allPlayerData.add(playerData);
			}
		} catch (SQLException e) {
			e.printStackTrace();
			CraftEconomy.getInstance().getLogger().info(" ");
			CraftEconomy.getInstance().getLogger().info("[CraftEconomy]An error occurred while reading player data from Mysql.".replace("&", "§"));
			CraftEconomy.getInstance().getLogger().info(" ");
		} finally {
			if (statement != null) {
				try {
					statement.close();
				} catch (SQLException ignored) { }
			}
		}
		return allPlayerData;
	}

	void insertPlayerData(String targetPlayer, double balance) {
		PreparedStatement statement = null;
		try {
			String sql = "insert into " + tablePrefix + "player (" + (CraftEconomy.getInstance().isOnlineMode() ? "uuid" : "name") + ",balance)values(?,?)";
			statement = connection.prepareStatement(sql);
			statement.setString(1, targetPlayer);
			statement.setDouble(2, balance);
			statement.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
			CraftEconomy.getInstance().getLogger().info(" ");
			CraftEconomy.getInstance().getLogger().info("[CraftEconomy]An error occurred while inserting player data from Mysql.".replace("&", "§"));
			CraftEconomy.getInstance().getLogger().info(" ");
		} finally {
			if (statement != null) {
				try {
					statement.close();
				} catch (SQLException ignored) { }
			}
		}
	}

	public void close() {
		try {
			connection.close();
		} catch (SQLException ignored) { }
	}
}
